import type { FC, MouseEvent } from "react";
import type { ViewTypes } from "./Views";
import type * as Controls from "./SideControls";
import type { SpectrogramScale } from "../../lib/AudioUltra/Analysis/FFTProcessor";

export type TimelineControls = Partial<Record<keyof typeof Controls, boolean>> & {
  ZoomControl: boolean;
  SpeedControl: boolean;
};

export interface TimelineProps<D extends ViewTypes = "frames"> {
  regions: any[];
  length: number;
  position: number;
  height?: number;
  mode: D;
  framerate: number;
  playing: boolean;
  buffering?: boolean;
  zoom?: number;
  volume?: number;
  speed?: number;
  fullscreen?: boolean;
  disableView?: boolean;
  className?: string;
  defaultStepSize?: number;
  allowFullscreen?: boolean;
  allowViewCollapse?: boolean;
  allowSeek?: boolean;
  hopSize?: number;
  altHopSize?: number;
  data?: any;
  controlsOnTop?: boolean;
  controls?: TimelineControls;
  customControls?: TimelineCustomControls[];
  readonly?: boolean;
  onReady?: (data: Record<string, any>) => void;
  onPlay?: () => void;
  onPause?: () => void;
  onFinished?: () => void;
  onSeek?: (position: number) => void;
  onPositionChange: (value: number) => void;
  onToggleVisibility?: (id: string, visibility: boolean) => void;
  onAddRegion?: (region: Record<string, any>) => any;
  onDeleteRegion?: (id: string) => void;
  onStartDrawing?: (options: { frame: number; region?: string }) => MSTTimelineRegion | undefined;
  onFinishDrawing?: (options: { mode?: "new" | "edit" }) => void;
  onZoom?: (zoom: number) => void;
  onSelectRegion?: (event: MouseEvent<HTMLDivElement>, id: string, select?: boolean) => void;
  onAction?: (event: MouseEvent, action: string, data?: any) => void;
  onVolumeChange?: (volume: number) => void;
  onFullscreenToggle?: (fullscreen: boolean) => void;
  onSpeedChange?: (speed: number) => void;
  formatPosition?: (options: TimelineControlsFormatterOptions) => string;
}

export interface TimelineViewProps {
  step: number;
  offset: number;
  position: number;
  length: number;
  playing: boolean;
  zoom?: number;
  speed?: number;
  volume?: number;
  regions: TimelineRegion[];
  height?: number;
  leftOffset?: number;
  controls?: TimelineControls;
  onScroll: (position: number) => void;
  onPositionChange: (position: number) => void;
  onResize: (position: number) => void;
  onPlay?: TimelineProps["onPlay"];
  onPause?: TimelineProps["onPause"];
  onSeek?: TimelineProps["onSeek"];
  onFinished?: TimelineProps["onFinished"];
  onToggleVisibility?: TimelineProps["onToggleVisibility"];
  onReady?: TimelineProps["onReady"];
  onZoom?: TimelineProps["onZoom"];
  onAddRegion?: TimelineProps["onAddRegion"];
  onDeleteRegion?: TimelineProps["onDeleteRegion"];
  onSelectRegion?: TimelineProps["onSelectRegion"];
  onStartDrawing?: TimelineProps["onStartDrawing"];
  onFinishDrawing?: TimelineProps["onFinishDrawing"];
  onVolumeChange?: TimelineProps["onVolumeChange"];
  onSpeedChange?: TimelineProps["onSpeedChange"];
}

// Full region stored in MST store
export interface MSTTimelineRegion {
  id: string;
  ranges: { start: number; end: number }[];
  object: { length: number }; // Video tag
  setRange: (range: [number, number], options?: { mode?: "new" | "edit" }) => void;
}

export interface TimelineRegion {
  id: string;
  index?: number;
  label: string;
  color: string;
  visible: boolean;
  selected: boolean;
  sequence: TimelineRegionKeyframe[];
  /** is this timeline region with spans */
  timeline?: boolean;
  locked?: boolean;
}

export interface TimelineRegionKeyframe {
  frame: number;
  enabled: boolean;
}

export interface TimelineContextValue {
  position: number;
  length: number;
  regions: TimelineRegion[];
  step: number;
  playing: boolean;
  visibleWidth: number;
  seekOffset: number;
  settings?: TimelineSettings;
  changeSetting?: (key: string, value: any) => void;
  data?: any;
  readonly?: boolean;
}

export interface TimelineMinimapProps {
  regions: TimelineRegion[];
  step: number;
  length: number;
}

export type TimelineSettings = {
  stepBackHotkey?: string;
  stepForwardHotkey?: string;
  playpauseHotkey?: string;
  stepAltBack?: string;
  stepAltForward?: string;
  skipToBeginning?: string;
  skipToEnd?: string;
  hopBackward?: string;
  hopForward?: string;
  fastTravelSize?: TimelineStepFunction;
  stepSize?: TimelineStepFunction;
  leftOffset?: number;
  loopRegion?: boolean;
  autoPlayNewSegments?: boolean;

  spectrogramFftSamples?: number;
  spectrogramWindowingFunction?: "hanning" | "hamming" | "blackman" | "sine";
  spectrogramColorScheme?: string;
  numberOfMelBands?: number;
  spectrogramMinDb?: number;
  spectrogramMaxDb?: number;
  spectrogramVisible?: boolean;
  spectrogramScale?: SpectrogramScale;
};

export type TimelineStepFunction = (
  length: number,
  position: number,
  regions: TimelineRegion[],
  direction: -1 | 1,
) => number;

export interface TimelineExtraControls<A extends string, D> {
  onAction?: <T extends Element>(e: MouseEvent<T>, action: A, data?: D) => void;
}

export type TimelineView<D extends FC<TimelineExtraControls<any, any>> = any> = {
  View: FC<TimelineViewProps>;
  Minimap?: FC<any>;
  Controls?: D;
  settings?: TimelineSettings;
};

export type TimelineControlsStepHandler = (e?: MouseEvent<HTMLButtonElement>, stepSize?: TimelineStepFunction) => void;

export interface TimelineControlsProps {
  length: number;
  position: number;
  frameRate: number;
  playing: boolean;
  collapsed: boolean;
  fullscreen: boolean;
  buffering?: boolean;
  volume?: number;
  speed?: number;
  zoom?: number;
  amp?: number;
  duration?: number;
  disableFrames?: boolean;
  extraControls?: JSX.Element | null;
  allowFullscreen?: boolean;
  allowViewCollapse?: boolean;
  controls?: TimelineProps["controls"];
  altHopSize?: TimelineProps["altHopSize"];
  customControls?: TimelineCustomControls[];
  mediaType: string;
  layerVisibility?: Map<string, boolean>;
  onRewind: (steps?: number) => void;
  onForward: (steps?: number) => void;
  onPositionChange: (position: number) => void;
  onToggleCollapsed: (collapsed: boolean) => void;
  onStepBackward: TimelineControlsStepHandler;
  onStepForward: TimelineControlsStepHandler;
  formatPosition?: TimelineProps["formatPosition"];
  onPlay?: TimelineProps["onPlay"];
  onPause?: TimelineProps["onPause"];
  onFullScreenToggle: TimelineProps["onFullscreenToggle"];
  onVolumeChange: TimelineProps["onVolumeChange"];
  onSpeedChange?: TimelineProps["onSpeedChange"];
  onZoom?: TimelineProps["onZoom"];
  onAmpChange?: (amp: number) => void;
  onSpectrogramFftSamplesChange?: (samples: number) => void;
  onNumberOfMelBandsChange?: (bands: number) => void;
  onSpectrogramWindowingFunctionChange?: (windowFunction: string) => void;
  onSpectrogramColorSchemeChange?: (colorScheme: string) => void;
  toggleVisibility?: (layerName: string, isVisible: boolean) => void;
}

export interface TimelineCustomControls {
  position: "left" | "right" | "leftCenter" | "rightCenter";
  component: JSX.Element | (() => JSX.Element);
}

export interface TimelineSideControlProps {
  position?: number;
  length?: number;
  volume?: number;
  onPositionChange?: TimelineControlsProps["onPositionChange"];
  onVolumeChange?: TimelineProps["onVolumeChange"];
}

export type TimelineControlsFormatterOptions = {
  time: number;
  position: number;
  fps: number;
  length: number;
};
